package net.xdclass.shopproject.spring;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ClassPathXmlApplicationContext implements BeanFactory{

    private Map<String, Object> beans = new HashMap<>();

    public ClassPathXmlApplicationContext() throws Exception {
        init();
    }

    /**
     * 去解析xml，获取bean信息
     *
     * @throws Exception
     */
    private void init() throws Exception {
        SAXBuilder sb = new SAXBuilder();
        Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
        Element rootElement = doc.getRootElement();
        List<Element> list = rootElement.getChildren("bean");
        for (int i = 0; i < list.size(); i++) {
            Element element = list.get(i);
            String id = element.getAttributeValue("id");
            String clazz = element.getAttributeValue("class");
            Object o = Class.forName(clazz).getDeclaredConstructor().newInstance();
            beans.put(id, o);

            List<Element> propertyList = element.getChildren("property");
            for (Element p : propertyList) {
                String name = p.getAttributeValue("name");
                String bean = p.getAttributeValue("bean");
                Object beanObject = beans.get(bean);
                Class<?> aClass = beanObject.getClass();
                String methodName = "set" + name.substring(0,1).toUpperCase() + name.substring(1);
                // 获取方法，传参是方法名称和方法形参
                Method method = o.getClass().getMethod(methodName, aClass);
                // 调用方法，传参是方法所属对象实例（也就是这个方法在哪个对象上）和方法实参
                method.invoke(o, beanObject);
            }
        }
    }

    @Override
    public Object getBean(String name) {
        return beans.get(name);
    }

    @Override
    public boolean containsBean(String name) {
        return beans.containsKey(name);
    }

    @Override
    public Class<?> getType(String name) {
        if (beans.containsKey(name)) {
            return beans.get(name).getClass();
        }
        return null;
    }
}
